package com.nidu.demo.excel.util;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.nidu.demo.dict.cache.DictCacheService;
import com.nidu.demo.excel.annotation.ExcelColumn;

import com.nidu.demo.i18n.util.I18nUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class ExcelExportUtil {

    private final DictCacheService dictCacheService;

    /** 导出 */
    public <T> void export(HttpServletResponse response, String fileName, Class<T> clazz, List<T> data) {
        List<List<String>> head = buildHead(clazz);
        List<List<Object>> rows = buildRows(clazz, data);

        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String encodedName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedName + ".xlsx");

            EasyExcel.write(response.getOutputStream())
                    .head(head)
                    .sheet(fileName)
                    .doWrite(rows);
        } catch (IOException e) {
            throw new RuntimeException("Excel导出失败", e);
        }
    }

    /** 生成导入模板（只包含表头） */
    public <T> void exportTemplate(HttpServletResponse response, String fileName, Class<T> clazz) {
        export(response, fileName, clazz, Collections.emptyList());
    }

    /** 生成表头 */
    private <T> List<List<String>> buildHead(Class<T> clazz) {
        return Arrays.stream(clazz.getDeclaredFields())
                .filter(f -> f.isAnnotationPresent(ExcelColumn.class))
                .sorted(Comparator.comparingInt(f -> f.getAnnotation(ExcelColumn.class).index()))
                .map(f -> {
                    ExcelColumn col = f.getAnnotation(ExcelColumn.class);
                    String header = StrUtil.isNotBlank(col.i18nKey())
                            ? I18nUtil.getMessage(col.i18nKey(), col.value())
                            : col.value();
                    return Collections.singletonList(header);
                }).collect(Collectors.toList());
    }

    /** 生成数据行 */
    private <T> List<List<Object>> buildRows(Class<T> clazz, List<T> data) {
        List<Field> fields = Arrays.stream(clazz.getDeclaredFields())
                .filter(f -> f.isAnnotationPresent(ExcelColumn.class))
                .sorted(Comparator.comparingInt(f -> f.getAnnotation(ExcelColumn.class).index()))
                .collect(Collectors.toList());

        List<List<Object>> rows = new ArrayList<>();
        for (T t : data) {
            List<Object> row = new ArrayList<>();
            for (Field field : fields) {
                field.setAccessible(true);
                try {
                    Object value = field.get(t);
                    ExcelColumn col = field.getAnnotation(ExcelColumn.class);

                    // 字典转换
                    if (StrUtil.isNotBlank(col.dictType()) && value != null) {
                        value = dictCacheService.toLabel(col.dictType(), String.valueOf(value));
                    }
                    // 日期格式化
                    if (value instanceof Date) {
                        value = new SimpleDateFormat(col.dateFormat()).format(value);
                    }
                    row.add(value);
                } catch (Exception ignored) {}
            }
            rows.add(row);
        }
        return rows;
    }
}
